package es.armaplus.business;

import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import es.armaplus.business.exceptions.BusinessException;
import es.armaplus.commons.Constantes;
import es.armaplus.dao.DaoFactory;
import es.armaplus.dao.PresupuestosDao;
import es.armaplus.dao.exceptions.DaoException;
import es.armaplus.ddbb.base.Clientes;
import es.armaplus.ddbb.base.PresupuestoEntrada;
import es.armaplus.ddbb.base.Presupuestos;


/**
 * Capa de negocios del modulo de presupuestos.
 * @author Texaco
 *
 */
public class PresupuestoBusiness extends BusinessBase {

	private final static Log log = LogFactory.getLog(PresupuestoBusiness.class);

	/**
	 * M�todo para crear o actualizar un presupuesto.
	 * 
	 * @param idPresupuesto
	 * @param idCliente
	 * @param descuento
	 * @param impuesto
	 * @param coleccionEntradasPresupuesto
	 * @throws DaoException 
	 * @throws BusinessException 
	 */
	public Presupuestos crearOActualizarPresupuesto(String idPresupuesto,
			String idCliente, 
			Double descuento, 
			Double impuesto,
			Collection coleccionEntradasPresupuesto) throws DaoException, BusinessException {
		
		log.debug(Constantes.METHOD_BEGIN);
		Presupuestos presupuesto = null;
		PresupuestosDao presupuestoD = null;
		ClienteBusiness clienteB = null;

		try {
			clienteB = (ClienteBusiness) BusinessFactory.getBusiness(BusinessFactory.CLIENTE_BUSINESS);
			presupuestoD = (PresupuestosDao) DaoFactory.getDao(DaoFactory.PRESUPUESTOS_DAO);
			if(idPresupuesto != null){
			log.debug("El presupuesto existe. Lo actualizamos");
				presupuesto = presupuestoD.getPresupuesto(Integer.valueOf(idPresupuesto));
			}else{
				log.debug("El presupuesto es nuevo. Creamos");
				presupuesto = new Presupuestos();
				presupuesto.setFechaAlta(new Date());
			}
			
			presupuesto.setClientes(clienteB.getCliente(idCliente));
			presupuesto.setDescuento(descuento);
			presupuesto.setImpuesto(impuesto);
			
			presupuestoD.guardar(presupuesto);
			
			// Borramos las posibles entradas del presupuesto.
			if(presupuesto.getPresupuestoEntradas() != null){
				for(Iterator iterator = presupuesto.getPresupuestoEntradas().iterator(); iterator.hasNext();){
					PresupuestoEntrada entrada = (PresupuestoEntrada) iterator.next();
					presupuestoD.borrar(entrada);
				}
				
			}
			
			//Guardamos las nuevas entradas del presupuesto.
			for (Iterator iterator = coleccionEntradasPresupuesto.iterator(); iterator
					.hasNext();) {
				PresupuestoEntrada entrada = (PresupuestoEntrada) iterator.next();
				entrada.setPresupuestos(presupuesto);
				presupuestoD.guardar(entrada);
			}
			
			log.debug("Numero de entradas: " + presupuesto.getPresupuestoEntradas().size());
			log.debug("Refresco el objeto:");
			presupuesto = presupuestoD.getPresupuesto(presupuesto.getIdPresupuesto());
			log.debug("Numero de entradas: " + presupuesto.getPresupuestoEntradas().size());
		} catch (DaoException e) {
			log.error("Error en el acceso a los datos. ", e);
			throw new DaoException(e);
		} catch (ClassNotFoundException e) {
			log.error("Error en el nombre de la clase dao. ", e);
			throw new BusinessException(e);
		}

		
		log.debug(Constantes.METHOD_END);
		return presupuesto;
	}

	public Collection getEntradas(Presupuestos presupuesto) 
		throws DaoException, 
		BusinessException {
		
		List <PresupuestoEntrada> listaEntradas = null;
		
		try {
			PresupuestosDao presupuestoD = (PresupuestosDao) 
				DaoFactory.getDao(DaoFactory.PRESUPUESTOS_DAO);
			listaEntradas = presupuestoD.getEntradas(presupuesto);
			log.debug("Numero de entradas: " + listaEntradas.size());
			
		} catch (DaoException e) {
			log.error("Error en el acceso a los datos. ", e);
			throw new DaoException(e);
		} catch (ClassNotFoundException e) {
			log.error("Error en el nombre de la clase dao. ", e);
			throw new BusinessException(e);
		}
		return listaEntradas;
		
	}

	/**
	 * M�todo para calcular el total de un presupuesto impuesto y descuento 
	 * incluido.
	 * @param presupuesto
	 * @return
	 * @throws BusinessException 
	 * @throws DaoException 
	 */
	public String getTotalImpDescInc(Presupuestos presupuesto) throws DaoException, BusinessException {
		String totalStr = null;
		double total = 0;
		
		total = sumaImporteEntradas(presupuesto);
		log.debug("Total de las entradas: " + total);
		
		total = aplicaDescuento(presupuesto, total);
		log.debug("Total aplicado descuento: " + total);
		
		total = aplicaImpuesto(presupuesto, total);
		log.debug("Total aplicado impuesto: " + total);
		
		totalStr = String.valueOf(total);
		log.debug("Total devuelto: " + totalStr);
		return totalStr;
	}

	/**
	 * M�todo para calcular el total de un presupuesto.
	 * @param presupuesto
	 * @return
	 * @throws BusinessException 
	 * @throws DaoException 
	 */
	public String getTotal(Presupuestos presupuesto) throws DaoException, BusinessException {
		String totalStr = null;
		double total = 0;
		
		total = sumaImporteEntradas(presupuesto);
		log.debug("Total de las entradas: " + total);
		
		totalStr = String.valueOf(total);
		log.debug("Total devuelto: " + totalStr);
		return totalStr;
	}

	private double aplicaImpuesto(Presupuestos presupuesto, double total) {
		double totalImpuesto = 0;
		totalImpuesto = total + (total * presupuesto.getImpuesto() / 100);
		return totalImpuesto;
	}

	private double aplicaDescuento(Presupuestos presupuesto, double total) {
		double totalDescuento = 0;
		totalDescuento = total - (total * presupuesto.getDescuento() / 100);
		return totalDescuento;
	}

	private double sumaImporteEntradas(Presupuestos presupuesto) throws DaoException, BusinessException {
		log.debug(Constantes.METHOD_BEGIN);
		PresupuestosDao presupuestoD = null;
		List <PresupuestoEntrada> entradas = null;
		double total = 0;
		try {
			presupuestoD = (PresupuestosDao) DaoFactory.getDao(DaoFactory.PRESUPUESTOS_DAO);
			entradas = presupuestoD.getEntradas(presupuesto);
			for (Iterator iterator = entradas.iterator(); iterator.hasNext();) {
				PresupuestoEntrada entrada = (PresupuestoEntrada) iterator.next();
				total = total +(entrada.getPrecioUnidad() * entrada.getCantidad());
			}
		} catch (DaoException e) {
			log.error("Error en el acceso a datos. ", e);
			throw e;
		} catch (ClassNotFoundException e) {
			log.error("Error en el nombre de la clase dao. ", e);
			throw new BusinessException(e);
		}

		log.debug(Constantes.METHOD_BEGIN);
		return total;
	}

	public Presupuestos getPresupuesto(String idPresupuesto) throws DaoException, BusinessException {
		Presupuestos presupuesto = null;
		try {
			PresupuestosDao presupuestoD = (PresupuestosDao) DaoFactory.getDao(DaoFactory.PRESUPUESTOS_DAO);
			presupuesto = presupuestoD.getPresupuesto(Integer.valueOf(idPresupuesto));
		} catch (DaoException e) {
			log.error("Error en el acceso a datos. ", e);
			throw e;
		} catch (ClassNotFoundException e) {
			log.error("Error en el nombre de la clase dao. ", e);
			throw new BusinessException(e);
		}
		return presupuesto;
	}

	/**
	 * Método para obtener los presupuestos de un cliente.
	 * @param cliente
	 * @return
	 * @throws DaoException
	 * @throws BusinessException
	 */
	public Collection<Presupuestos> getPresupuestos(Clientes cliente) 
		throws DaoException, BusinessException {
		PresupuestosDao presupuestoD = null;
		Collection<Presupuestos> presupuestos = null;
		try {
			presupuestoD = (PresupuestosDao) DaoFactory.getDao(DaoFactory.PRESUPUESTOS_DAO);
			presupuestos = presupuestoD.getPrespuestos(cliente);
		} catch (DaoException e) {
			log.error("Error en el acceso a datos. ", e);
			throw e;
		} catch (ClassNotFoundException e) {
			log.error("Error en el nombre de la clase dao. ", e);
			throw new BusinessException(e);
		}
		return presupuestos;
	}
	
	/**
	 * Obtener el valor del impuesto de un presupuesto.
	 */
	public String getImpuesto(Presupuestos presupuesto) throws DaoException, BusinessException{
		double impuesto = aplicaDescuento(presupuesto, 
				sumaImporteEntradas(presupuesto)) *
				presupuesto.getImpuesto()/100;
		return String.valueOf(impuesto);
	}

	/**
	 * Obtener el valor del descuento.
	 * @throws BusinessException 
	 * @throws DaoException 
	 */
	public String getDescuento(Presupuestos presupuesto) throws DaoException, 
		BusinessException{
		double descuento = sumaImporteEntradas(presupuesto)*
			presupuesto.getDescuento()/100;
		return String.valueOf(descuento);
	}
}
